#include "uart.h"
#include "i2c.h"
#include "timer.h"
#include "wdt.h"
#include "pwm.h"

/* FreeRTOS handlers */
extern void xPortSysTickHandler(void);
extern void xPortPendSVHandler(void);
extern void vPortSVCHandler(void);

/* internal reset handlers */
void reset_handler(void);
static void isr_hard_fault(void);
static void isr_default(void);

/* reference to main application */
extern void main(void);

/* find following variables in linker script */
extern void _vStackTop(void);
extern unsigned long _etext;
extern unsigned long _data;
extern unsigned long _edata;

/**
 * Interrupt vector table
 *
 * @brief  this table contains all interrupt vectors
 *
 */
__attribute__ ((section(".isr_vector")))
void (* const isr_vector_table[])(void) =
{
        (void *)&_vStackTop,
        reset_handler,
        isr_default,
        isr_hard_fault,
        isr_default,
        isr_default,
        isr_default,
        0,
        0,
        0,
        0,
        vPortSVCHandler,
        isr_default,
        0,
        xPortPendSVHandler,
        xPortSysTickHandler,
        wdt_isr,          	// 16, 0x40 - WDT
        isr_default,	 	// 17, 0x44 - TIMER0
        isr_default,		// 18, 0x48 - TIMER1
        timer2_isr,    	  	// 19, 0x4c - TIMER2
        isr_default,		// 20, 0x50 - TIMER3
        uart0_isr,     	 	// 21, 0x54 - UART0
        isr_default,		// 22, 0x58 - UART1
        isr_default,		// 23, 0x5c - UART2
        isr_default,		// 24, 0x60 - UART3
        pwm1_irq,         	// 25, 0x64 - PWM1
        isr_default,		// 26, 0x68 - I2C0
        isr_default,		// 27, 0x6c - I2C1
        i2c2_master_isr, 	// 28, 0x70 - I2C2
        isr_default,		// 29, 0x74 - SPI
        isr_default,		// 30, 0x78 - SSP0
        isr_default,		// 31, 0x7c - SSP1
        isr_default,		// 32, 0x80 - PLL0 (Main PLL)
        isr_default,		// 33, 0x84 - RTC
        isr_default,		// 34, 0x88 - EINT0
        isr_default,		// 35, 0x8c - EINT1
        isr_default,		// 36, 0x90 - EINT2
        isr_default,		// 37, 0x94 - EINT3
        isr_default,		// 38, 0x98 - ADC
        isr_default,		// 39, 0x9c - BOD
        isr_default,		// 40, 0xA0 - USB
        isr_default,		// 41, 0xA4 - CAN
        isr_default,		// 42, 0xA8 - GP DMA
        isr_default,		// 43, 0xAc - I2S
        isr_default,		// 44, 0xB0 - Ethernet.
        isr_default,		// 45, 0xB4 - RITINT
        isr_default,		// 46, 0xB8 - Motor Control PWM
        isr_default,		// 47, 0xBc - Quadrature Encoder
        isr_default,		// 48, 0xC0 - PLL1 (USB PLL)
};

/**
 * Reset Entry Point
 *
 * @param  none
 * @return none
 *
 * @brief  this is the very first function, that gets executed
 * 		   initialize the data and bss segment of the controller
 * 		   call main function
 *
 */
void reset_handler(void)
{
    unsigned long *pulSrc, *pulDest;

    /* copy data segment initializers */
    pulSrc = &_etext;
    for (pulDest = &_data; pulDest < &_edata;)
    {
        *pulDest++ = *pulSrc++;
    }

    /* fill the bss segment with zeros, use assembly here to avoid overwriting own index */
    __asm("    ldr     r0, =_bss\n"
            "    ldr     r1, =_ebss\n"
            "    mov     r2, #0\n"
            "    .thumb_func\n"
            "zero_loop_bss:\n"
            "        cmp     r0, r1\n"
            "        it      lt\n"
            "        strlt   r2, [r0], #4\n"
            "        blt     zero_loop_bss");

		/* call main application */
        main();
        /* should never reach here */
}



static void isr_hard_fault(void)
{
    ui_printf("\n hard fault\n");
    while(1);
}


static void isr_default(void)
{
    ui_printf("\n service routine not set\n");
    while (1)
    {
    }
}
